package com.bestcem.xm.ticket.controller.v2;

import cn.hutool.core.lang.ObjectId;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.bestcem.xm.common.core.domain.web.ServiceResult;
import com.bestcem.xm.common.core.domain.web.XmResultJson;
import com.bestcem.xm.common.core.enums.ReqErrorCodeEnum;
import com.bestcem.xm.common.core.enums.ResourceErrorCodeEnum;
import com.bestcem.xm.common.core.enums.ValidationErrorCodeEnum;
import com.bestcem.xm.component.security.context.SecurityContextHolder;
import com.bestcem.xm.ticket.controller.param.CascadeExcelParam;
import com.bestcem.xm.ticket.controller.param.PageParam;
import com.bestcem.xm.ticket.controller.param.ticket.template.TemplateParam;
import com.bestcem.xm.ticket.controller.param.ticket.template.UpdateTemplateParam;
import com.bestcem.xm.ticket.controller.vo.SimpleIdVO;
import com.bestcem.xm.ticket.controller.vo.template.GetRecentTemplateVO;
import com.bestcem.xm.ticket.controller.vo.ticket.template.GetTemplateInfoVO;
import com.bestcem.xm.ticket.controller.vo.ticket.template.GetTemplateVO;
import com.bestcem.xm.ticket.controller.vo.ticket.template.ParseCascadeExcelVO;
import com.bestcem.xm.ticket.entity.mongo.TicketTemplateV2;
import com.bestcem.xm.ticket.enums.TemplateTypeEnum;
import com.bestcem.xm.ticket.service.TemplateService;
import com.bestcem.xm.ticket.util.TemplateCheckUtil;
import com.bestcem.xm.ticket.util.TicketEasyExcelListener;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * 工单模板相关的增删改查
 *
 * @author xuan.yang <xuan.yang@idiaoyan.com>
 * @version v2.3
 * @date 2021/9/1 18:24
 */
@Slf4j
@RestController(value = "TicketV2TemplateController")
@RequestMapping(value = "/ticket/v2", produces = MediaType.APPLICATION_JSON_VALUE)
public class TemplateController {

    public static final String ORG_ID_ILLEGAL = "orgId不合法";
    public static final String USER_ID_ILLEGAL = "userId不合法";
    public static final String LOGIN_ERROR = "登录信息错误";

    @Resource
    TemplateService templateService;
    @Autowired
    private HttpServletRequest request;

    /**
     * 获取最近使用的模板
     *
     * @param orgId
     * @param userId
     * @return
     * @author xuan.yang
     */
    @GetMapping("/ticket/recent_use_template/")
    public XmResultJson<GetRecentTemplateVO> getRecentUseTemplate(@RequestParam("org_id") String orgId, @RequestParam("user_id") String userId) {
        String checkResult = verifyGetRecentUseTemplateParam(orgId, userId);
        if (StrUtil.isNotBlank(checkResult)) {
            return XmResultJson.fail(ReqErrorCodeEnum.PARAM_FORMAT, checkResult);
        }
        ServiceResult<GetRecentTemplateVO> serviceResult = templateService.getRecentUseTemplate(orgId, userId);
        if (serviceResult.isSuccess()) {
            return XmResultJson.success(serviceResult.getData());
        } else {
            return XmResultJson.fail(ReqErrorCodeEnum.TEMPLATE_NOT_EXIST, serviceResult.getMsg());
        }

    }

    /**
     * 如果校验没有错误返回null
     * 否则返回错误提示信息
     *
     * @param orgId
     * @param userId
     * @return
     * @author xuan.yang
     */
    private String verifyGetRecentUseTemplateParam(String orgId, String userId) {
        if (!ObjectId.isValid(orgId)) {
            return ORG_ID_ILLEGAL;
        }
        if (!ObjectId.isValid(userId)) {
            return USER_ID_ILLEGAL;
        }
        /**
         * 判断是否登录
         */
        if (ObjectUtil.hasEmpty(SecurityContextHolder.getUserId(), SecurityContextHolder.getOrgId())) {
            return LOGIN_ERROR;
        }

        /**
         * 判断登录信息和传来的信息是否一直
         */
        if (!StrUtil.equals(SecurityContextHolder.getUserId(), userId) || !StrUtil.equals(SecurityContextHolder.getOrgId(), orgId)) {
            // 此时登陆信息和传来的信息不一致,可能改了token
            log.info("[ticket] loginInfo not correct--userid,{},orgId{}----param userId{},orgId{}", SecurityContextHolder.getUserId(), SecurityContextHolder.getOrgId(), userId, orgId);
            return LOGIN_ERROR;
        }

        return null;
    }

    /**
     * 新增工单模板
     *
     * @param templateParam
     * @return
     * @author xuan.yang
     */
    @PostMapping("/template")
    public XmResultJson<SimpleIdVO> template(@RequestBody TemplateParam templateParam) {
        String orgId = SecurityContextHolder.getOrgId();
        String userId = SecurityContextHolder.getUserId();
        ServiceResult<String> serviceResult = templateService.insertTemplate(templateParam, orgId, userId);
        if (serviceResult.isSuccess()) {
            return XmResultJson.success(SimpleIdVO.getInstance(serviceResult.getData()));
        }
        return XmResultJson.fail(Integer.valueOf(serviceResult.getErrorCode()), serviceResult.getMsg());

    }

    /**
     * 修改模板
     *
     * @param id                  模板主键
     * @param updateTemplateParam 修改模板所需参数
     * @return 修改成功与否信息
     * @author ympan <yuming.pan@idiaoyan.com>
     * @date 18:00 2021/9/3
     */
    @PutMapping("/template/{id}")
    public XmResultJson<SimpleIdVO> updateTemplate(@PathVariable String id, @RequestBody UpdateTemplateParam updateTemplateParam) {
        String orgId = SecurityContextHolder.getOrgId();
        String userId = SecurityContextHolder.getUserId();
        XmResultJson checkResult = TemplateCheckUtil.checkUpdateTemplateParam(updateTemplateParam, orgId, userId, id);
        if (0 != checkResult.getCode()) {
            return checkResult;
        }
        ServiceResult<String> serviceResult = templateService.updateTemplate(id, updateTemplateParam, orgId, userId);
        if (serviceResult.isSuccess()) {
            return XmResultJson.success(SimpleIdVO.getInstance(serviceResult.getData()));
        } else {
            return XmResultJson.fail(serviceResult.getErrorData(), serviceResult.getMsg());
        }
    }

    /**
     * 通过模板id获取详情
     *
     * @param templateId
     * @return
     */
    @GetMapping("/template/{templateId}")
    public XmResultJson<GetTemplateInfoVO> getTemplate(@PathVariable String templateId) {
        if (!ObjectId.isValid(templateId)) {
            return XmResultJson.fail(5, "模板id错误");
        }
        ServiceResult<GetTemplateInfoVO> templateV2ServiceResult = templateService.getTemplateById(templateId);
        if (!templateV2ServiceResult.isSuccess()) {
            return XmResultJson.fail(5, templateV2ServiceResult.getMsg());
        }
        return XmResultJson.success(templateV2ServiceResult.getData());
    }

    /**
     * 根据id删除模板
     *
     * @param templateId
     * @return
     */
    @DeleteMapping("/template/{templateId}")
    public XmResultJson<SimpleIdVO> deleteTemplate(@PathVariable String templateId) {
        String orgId = SecurityContextHolder.getOrgId();
        if (!ObjectId.isValid(templateId)) {
            return XmResultJson.fail(5, "模板id错误");
        }
        ServiceResult<TicketTemplateV2> templateV2ServiceResult = templateService.deleteTemplateById(templateId, orgId);
        if (templateV2ServiceResult.isSuccess()) {
            return XmResultJson.success(SimpleIdVO.getInstance(templateId));
        } else {
            return XmResultJson.fail(5, templateV2ServiceResult.getMsg());
        }
    }

    /**
     * 模板分页接口
     *
     * @param size        每页条数
     * @param page        页数
     * @param type        模板类型
     * @param listAllFlag 全量查找flag true：全量查找 false：分页查找
     * @return 模板分页数据
     * @author ympan <yuming.pan@idiaoyan.com>
     * @date 17:50 2021/9/2
     */
    @GetMapping("/template/")
    public XmResultJson<GetTemplateVO> listTemplate(@RequestParam(required = false) Integer size,
                                                    @RequestParam(required = false) Integer page,
                                                    @RequestParam(required = false) Integer type,
                                                    @RequestParam("list_all") Boolean listAllFlag) {
        String orgId = SecurityContextHolder.getOrgId();
        // 校验入参
        XmResultJson<GetTemplateVO> verifyResult = verifyGetTemplateParam(size, page, type, orgId, listAllFlag);
        if (verifyResult.getCode() != 0) {
            return verifyResult;
        }
        // 构建分页参数
        PageParam pageParam = new PageParam(page, size);

        ServiceResult<GetTemplateVO> getTemplateResult = templateService.listTemplate(type, pageParam, orgId, listAllFlag);
        if (getTemplateResult.isSuccess()) {
            return XmResultJson.success(getTemplateResult.getData());
        }
        return XmResultJson.fail(getTemplateResult.getErrorData(), getTemplateResult.getMsg());
    }

    /**
     * 校验模板分页接口入参
     *
     * @param size 每页条数
     * @param page 页数
     * @param type 模板类型
     * @return 校验成功与否
     * @author ympan <yuming.pan@idiaoyan.com>
     * @date 17:18 2021/9/6
     */
    private XmResultJson<GetTemplateVO> verifyGetTemplateParam(Integer size, Integer page, Integer type, String orgId, Boolean listAllFlag) {
        if (StringUtils.isEmpty(orgId)) {
            return XmResultJson.fail(ReqErrorCodeEnum.PARAM_LOST, "公司id为空");
        }
        if (!ObjectId.isValid(orgId)) {
            return XmResultJson.fail(ReqErrorCodeEnum.PARAM_FORMAT, "公司id格式错误");
        }
        if (Objects.isNull(listAllFlag)) {
            return XmResultJson.fail(ReqErrorCodeEnum.PARAM_LOST, "缺少list_all参数");
        }
        // 如果不是全量查询的话，则需进行分页参数校验；如果是全量查询的话，则需对type进行校验
        if (Boolean.FALSE.equals(listAllFlag)) {
            if (Objects.isNull(size)) {
                return XmResultJson.fail(ReqErrorCodeEnum.PARAM_LOST, "缺少size参数");
            }
            if (Objects.isNull(page)) {
                return XmResultJson.fail(ReqErrorCodeEnum.PARAM_LOST, "缺少page参数");
            }
            if (page <= 0) {
                return XmResultJson.fail(ReqErrorCodeEnum.PARAM_RANGE, "page不在范围内");
            }
            if ((size <= 0 || size >= 999)) {
                return XmResultJson.fail(ReqErrorCodeEnum.PARAM_RANGE, "size不在范围内");
            }
        } else {
            if (Objects.isNull(type)) {
                return XmResultJson.fail(ReqErrorCodeEnum.PARAM_LOST, "缺少type参数");
            }
        }
        if (Objects.nonNull(type)) {
            TemplateTypeEnum templateTypeEnum = TemplateTypeEnum.getByIndex(type);
            if (Objects.isNull(templateTypeEnum)) {
                return XmResultJson.fail(ReqErrorCodeEnum.PARAM_RANGE, "type不在范围内");
            }
        }
        return XmResultJson.success();
    }

    /**
     * 解析excel文件
     *
     * @param file 级联“选项”和“选项提示”的excel文件
     * @return ParseCascadeExcelVO集合
     * @author ympan <yuming.pan@idiaoyan.com>
     * @date 21:22 2021/9/4
     */
    @PostMapping(value = "/template/select/import", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public XmResultJson<ParseCascadeExcelVO> parseCascadeExcel(@RequestPart(name = "file") MultipartFile file) {
        List<List<Object>> rows = null;
        List<List<Object>> optionHint = null;
        try {
            String fileName = file.getOriginalFilename();
            if (ObjectUtils.isEmpty(fileName) || fileName.length() < 6) {
                return XmResultJson.fail(ValidationErrorCodeEnum.FILE_TYPE_NOT_RIGHT, ResourceErrorCodeEnum.INVALID_FORMAT.getMsg());
            }
            if (fileName.lastIndexOf(".xlsx") != fileName.length() - 5) {
                return XmResultJson.fail(ValidationErrorCodeEnum.FILE_TYPE_NOT_RIGHT, ResourceErrorCodeEnum.INVALID_FORMAT.getMsg());
            }
            if (file.getSize() / 1048576L > 10L) {
                return XmResultJson.fail(ResourceErrorCodeEnum.FILE_TOO_LARGE, "文件过大");
            }
            InputStream inputStream = file.getInputStream();

            // EasyExcel读取数据
            TicketEasyExcelListener<CascadeExcelParam> excelListener = new TicketEasyExcelListener<>();
            EasyExcel.read(inputStream, CascadeExcelParam.class, excelListener).sheet().headRowNumber(2).doRead();
            List<CascadeExcelParam> cascadeExcelParams = excelListener.getResult();
            if (!CollectionUtils.isEmpty(cascadeExcelParams)) {
                // 获取hint数据
                CascadeExcelParam hint = cascadeExcelParams.get(0);
                List<Object> hints = Arrays.asList(hint.getRow1(), hint.getRow2(), hint.getRow3(), hint.getRow4(), hint.getRow5());
                List<List<Object>> hintLists = new ArrayList<>();
                hintLists.add(hints);
                optionHint = hintLists;
                // 获取rows数据
                cascadeExcelParams.remove(0);
                List<List<Object>> rowLists = new ArrayList<>();
                for (CascadeExcelParam row : cascadeExcelParams) {
                    List<Object> rowList = Arrays.asList(row.getRow1(), row.getRow2(), row.getRow3(), row.getRow4(), row.getRow5());
                    rowLists.add(rowList);
                }
                rows = rowLists;
            }

        } catch (Exception e) {
            return XmResultJson.fail(ResourceErrorCodeEnum.INVALID_FORMAT, ResourceErrorCodeEnum.INVALID_FORMAT.getMsg());
        }
        ServiceResult<ParseCascadeExcelVO> result = templateService.parseCascadeExcel(optionHint, rows);
        if (result.isSuccess()) {
            return XmResultJson.success(result.getData());
        }
        return XmResultJson.fail(result.getErrorData(), result.getMsg());
    }
}
